package com.sxds.wn.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.util.WebUtils;


/**
 * <p>Title:Java反射辅助公共类</p>
 * <p>Description:Java提供了一套机制来动态执行方法和构造方法，以及数组操</p>
 * <p>Copyright: Copyright (c) 2006</p>
 * <p>Company: B2BOnline</p>
 * @author <a href="mailto:tangwenzhong@foresee.com.cn">tangtao</a>
 * <p/>
 */

public class ReflectUtil {
	
	/**
	 * log4j logger holder
	 */
	private static final Log logger = LogFactory.getLog(ReflectUtil.class);

	public static final String modelClassName = "modelClassName";
	
	public static Object getObject(HttpServletRequest request,String className) throws Exception{
		if( className==null || "".equals(className) ){
			className = request.getParameter(modelClassName);
		}
		if( className==null || "".equals(className) ){
			return null;
		}
		Object bean = getObject(WebUtils.getParametersStartingWith(request, null),className);
		//Object bean = newInstance(className, null);
		//BeanUtils.populate(bean, WebUtils.getParametersStartingWith(request, null));
		return bean;
	}
	
	/**
	 * 将HashMap中的（parameName,value)值设置产生数据DTO(Data transmision object)对象<br/>
	 * 主要是针对单个java model object 对象使用自动设置对象属性值
	 * @param paramValues key->value,form表单中的parameName和parameValue
	 * @param className 要产生的实例名,一般为Data Model Object(数据模型),class 需要带默认构造方法
	 * @return className的实例，设置其属性值
	 * @throws Exception 设置过程中发生错误
	 */
	public static Object getObject(Map paramValues,String className) throws Exception{
		Assert.notNull(paramValues,"Map parameValues must not be null");
		Assert.notNull(className,"className param must not be null");
		Assert.notEmpty(paramValues ,"parameValues's elements must more than 1 element");
		Assert.hasText(className,"className must not be empty");
		Object instance = newInstance(className, null);
		Field[] fields = instance.getClass().getDeclaredFields();
		logger.debug("begin to initial " + className + " ant it's value");
		for( int i=0;i<fields.length;i++ ){
			//获取属性名称
			String fieldName = fields[i].getName();
			//从HashMap中获取该值对应名称参数
			Object valueObject = paramValues.get(fieldName);
			//判断HashMap中是否存在相应的值，不存在则循环下一属性名
			if( valueObject==null || "".equals(valueObject)) continue;
			//调用设置方法的参数
			Object[] args = null;
			Class fieldClass = fields[i].getType();
			//默认为set开头的设置方法
			String setMethodName = "set" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
			if( fieldName.startsWith("is") ){//如果是is开头的变量，则需要代替修改设置方法值
				if( fieldClass.isAssignableFrom(boolean.class) || fieldClass.isAssignableFrom(Boolean.class) 
					|| (fieldClass.isArray() && 
							(fieldClass.getComponentType().isAssignableFrom(boolean.class) 
									|| fieldClass.getComponentType().isAssignableFrom(Boolean.class))) ){
					setMethodName = "set" + fieldName.substring(2);
				}
			}
			//获取属性设置调用方法
			Method setMethod = null;
			try{
				setMethod = instance.getClass().getMethod(setMethodName,new Class[] { fields[i].getType() });
			}catch(Exception ex){
				continue;			
			}
			if( fieldClass.isAssignableFrom(String.class) ){
				//简单字符串类型值
				logger.debug(fieldName + " is string...........");
				args = new Object[]{ valueObject };
			} else if( fieldClass.isArray() && fieldClass.getComponentType().isAssignableFrom(String.class)){
				//字符串数字数组
				logger.debug(fieldName + " is string array ...........");
				args = new Object[]{(Object[])valueObject};
			}else if( fieldClass.isPrimitive()){
				//判断是否为primitive类型数据
				logger.debug(fieldName + " is primitive...........");
				args = new Object[]{getPrimitiveValue(fieldClass, (String)valueObject)};			
			}else if( ClassUtils.isPrimitiveArray(fieldClass) ){
				//原始数组数据类型
				logger.debug(fieldName + " is primitive array...........");
				args = new Object[]{getPrimitiveValues(fieldClass.getComponentType(), (String[])valueObject)};
			}else if( ClassUtils.isPrimitiveWrapper(fieldClass) ){
				//原始数据类型的封装，如int-->Integer,long-->Long等
				logger.debug(fieldName + " is primitive warpper...........");
				args = new Object[]{getPrimitiveWrapperValue(fieldClass, (String)valueObject)};
			}else if( ClassUtils.isPrimitiveWrapperArray(fieldClass) ){
				//原始数据类型数组封装,如 Integer-->new Integer[](),Long-->new Long[]()等
				logger.debug(fieldName + " is primitive warpper array...........");
				args = new Object[]{getPrimitiveWrapperValues(fieldClass.getComponentType(), (String[])valueObject)};
			}else if( fieldClass.isAssignableFrom(java.util.Date.class) ){
				//判断是否为日期格式数据类型,普通日期格式内容
				logger.debug(fieldName + " is java.lang.Date patter");
				args = new Object[]{ DateUtil.parseDate((String)valueObject, DateUtil.getDatePattern((String)valueObject))};
			}else if( fieldClass.isAssignableFrom(java.sql.Date.class) ){
				//判断是否为sql日期格式类型，将内容转换为java.sql.Date格式内容
				logger.debug(fieldName + " is java.lang.Date patter");
				args = new Object[]{ DateUtil.parseSqlDate((String)valueObject, DateUtil.getDatePattern((String)valueObject))};
			}else{
				//普通的用户自定义类型的数据对象
				logger.debug(fieldName + " is java model object...........");
			}
			setMethod.invoke(instance, args);
		}
		return instance;
	}

	/**
	 * 获取某个对象的属性
	 * @param owner
	 * @param fieldName
	 * @return
	 * @throws Exception
	 */
	public static Object getProperty(Object owner,String fieldName) throws Exception{
		Class ownerClass = owner.getClass();
		Field field = ownerClass.getField( fieldName );
		return field.get( owner );
	}
	
	/**
	 * 获取某对象的静态属性
	 * @param className 类名
	 * @param fieldName 属性名
	 * @return
	 * @throws Exception
	 */
	public static Object getStaticProperty(String className,String fieldName) throws Exception{
		Class onwerClass = Class.forName(className);
		Field field = onwerClass.getField( fieldName );
		return field.get( onwerClass );
	}
	
	/**
	 * 执行某对象的方法
	 * @param owner
	 * @param methodName
	 * @param args
	 * @return
	 * @throws Exception
	 */
	
	public static Object invokeMethod(Object owner,String methodName,Object[] args) throws Exception{
		Class ownerClass = owner.getClass();
		Class[] argsClass = new Class[ args.length ];
		for( int i=0;i<args.length;i++ ){
			argsClass[i] = args[i].getClass();
		}
		Method method = ownerClass.getMethod(methodName,argsClass);
		return method.invoke(owner, args);
	}

	/**
	 * 执行某个类的静态方法
	 * @param className
	 * @param methodName
	 * @param args
	 * @return
	 * @throws Exception
	 */
	public static Object invokeStaticMethod(String className,String methodName,Object[] args) throws Exception{
		Class onwerClass = Class.forName(className);
		Class[] argsClass = new Class[ args.length ];
		for( int i=0;i<args.length;i++ ){
			argsClass[i] = args[i].getClass();
		}
		Method method = onwerClass.getMethod(methodName, argsClass);
		return method.invoke(null, args);
	}
	
	/**
	 * 构造实例
	 * @param className
	 * @param args
	 * @return
	 * @throws Exception
	 */
	public static Object newInstance(String className,Object[] args) throws Exception{
		Class onwerClass = Class.forName(className);
		if( args==null || args.length==0 ){
			return onwerClass.newInstance();
		}
		Class[] argsClass = new Class[args.length];
		for( int i=0;i<args.length;i++ ){
			argsClass[i] = args[i].getClass();
		}
		Constructor cons = onwerClass.getConstructor(argsClass);
		return cons.newInstance(args);
	}
	
	/**
	 * 判断是否为某个类的实例
	 * @param obj
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	public static boolean isInstance(Object obj,Class clazz) throws Exception{
		return clazz.isInstance(obj);
	}
	
	/**
	 * 
	 * @param fieldClass
	 * @param value
	 * @return
	 * @throws Exception
	 */
	private static Object getPrimitiveValue(Class fieldClass,String value) throws Exception{
		if( fieldClass.isAssignableFrom(int.class) ){
			return new Integer(StringUtil.getIntValue(value));
		}else if( fieldClass.isAssignableFrom(short.class) ) {
			return new Short(StringUtil.getShortValue(value));
		}else if( fieldClass.isAssignableFrom(long.class) ){
			return new Long(StringUtil.getLongValue(value));
		}else if( fieldClass.isAssignableFrom(float.class) ){
			return new Float(StringUtil.getFloatValue(value));
		}else if( fieldClass.isAssignableFrom(double.class) ){
			return new Double(StringUtil.getDoubleValue(value));
		}else if( fieldClass.isAssignableFrom(boolean.class) ){
			return Boolean.valueOf(StringUtil.getBooleanValue(value));
		}else {
			throw new Exception("未知数据类型,无法转换赋值");
		}
	}
	
	/**
	 * 
	 * @param fieldClass
	 * @param values
	 * @return
	 * @throws Exception
	 */
	private static Object getPrimitiveValues(Class fieldClass,String[] values) throws Exception{
		if( fieldClass.isAssignableFrom(int.class) ){
			return StringUtil.getIntArrayValue(values);
		}else if( fieldClass.isAssignableFrom(short.class) ) {
			return StringUtil.getShortArrayValue(values);
		}else if( fieldClass.isAssignableFrom(long.class) ){
			return StringUtil.getLongArrayValue(values);
		}else if( fieldClass.isAssignableFrom(float.class) ){
			return StringUtil.getFloatArrayValue(values);
		}else if( fieldClass.isAssignableFrom(double.class) ){
			return StringUtil.getDoubleArrayValue(values);
		}else if( fieldClass.isAssignableFrom(boolean.class) ){
			return StringUtil.getBooleanArrayValue(values);
		}else {
			throw new Exception("未知数据类型,无法转换赋值");
		}
	}
	/**
	 * 
	 * @param fieldClass
	 * @param value
	 * @return
	 * @throws Exception
	 */
	
	private static Object getPrimitiveWrapperValue(Class fieldClass,String value) throws Exception{
		if( fieldClass.isAssignableFrom(Integer.class) ){
			return StringUtil.getIntegerWrapperValue(value);
		}else if( fieldClass.isAssignableFrom(Short.class) ) {
			return StringUtil.getShortWrapperValue(value);
		}else if( fieldClass.isAssignableFrom(Long.class) ){
			return StringUtil.getLongWrapperValue(value);
		}else if( fieldClass.isAssignableFrom(Float.class) ){
			return StringUtil.getFloatWrapperValue(value);
		}else if( fieldClass.isAssignableFrom(Double.class) ){
			return StringUtil.getDoubleWrapperValue(value);
		}else if( fieldClass.isAssignableFrom(Boolean.class) ){
			return StringUtil.getBooleanWrapperValue(value);
		}else {
			throw new Exception("未知数据类型,无法转换赋值");
		}
	}
	
	/**
	 * 
	 * @param fieldClass
	 * @param value
	 * @return
	 * @throws Exception
	 */
	private static Object[] getPrimitiveWrapperValues(Class fieldClass,String[] value) throws Exception{
		if( fieldClass.isAssignableFrom(Integer.class) ){
			return StringUtil.getIntegerWrapperArrayValue(value);
		}else if( fieldClass.isAssignableFrom(Short.class) ) {
			return StringUtil.getShortWrapperArrayValue(value);
		}else if( fieldClass.isAssignableFrom(Long.class) ){
			return StringUtil.getLongWrapperArrayValue(value);
		}else if( fieldClass.isAssignableFrom(Float.class) ){
			return StringUtil.getFloatWrapperArrayValue(value);
		}else if( fieldClass.isAssignableFrom(Double.class) ){
			return StringUtil.getDoubleWrapperArrayValue(value);
		}else if( fieldClass.isAssignableFrom(Boolean.class) ){
			return StringUtil.getBooleanWrapperArrayValue(value);
		}else {
			throw new Exception("未知数据类型,无法转换赋值");
		}
	}
	
	/**
	 * 将指定的model对象转发为输出javascript脚本对象
	 * @param object model实体
	 * @return 实体脚本对象（javascript)
	 * @throws Exception 解析过程发生错误
	 */
	public static String toJavascript(Object object) throws Exception{
		if( object==null ) return "{}";
		StringBuilder script = new StringBuilder("{");
		java.lang.reflect.Field[] fields = object.getClass().getDeclaredFields();
		if( fields!=null && fields.length>0 ){
			for(int i=0;i<fields.length;i++ ){
				//使用属性访问方法访,先改该属性为可访问属性
				ReflectionUtils.makeAccessible(fields[i]);				
				String propertyName = fields[i].getName();
				script.append(propertyName);
				script.append(": ");
				Object propertyValue = fields[i].get(object);
				Class fieldClass = fields[i].getType();
				//处理是否为null值的数据
				if( fieldClass.isAssignableFrom(String.class) ){
					//简单字符串类型值
					if( propertyValue==null ){
						script.append("''");
					}else{
						script.append("'").append(propertyValue).append("'");
					}					
				} else if( fieldClass.isArray() && fieldClass.getComponentType().isAssignableFrom(String.class)){
					//字符串数字数组
					if( propertyValue==null ){
						script.append("new Array()");
					}else{
						Object[] arrays = new Object[]{(Object[])propertyValue};
						script.append(" new Array(");
						for(int j=0;j<arrays.length;j++ ){
							script.append("'").append(arrays[j]).append("'");
							if( j!=arrays.length-1 ) script.append(",");
						}
						script.append(")");
					}
				}else if( fieldClass.isPrimitive()){
					//判断是否为primitive类型数据
					if( fieldClass.isAssignableFrom(char.class) ){
						script.append("'").append(propertyValue.toString()).append("'");
					}else{
						script.append(propertyValue);
					}					
				}else if( ClassUtils.isPrimitiveArray(fieldClass) ){
					//原始数组数据类型
					if( propertyValue==null ){
						script.append("new Array()");
					}else{
						Class componetType = propertyValue.getClass().getComponentType();
						if( componetType.isAssignableFrom(boolean.class)){
							boolean[] arrays = (boolean[])propertyValue;
							script.append(" new Array").append( Arrays.toString(arrays) );
						}else if( componetType.isAssignableFrom(byte.class)){
							byte[] arrays = (byte[])propertyValue;
							script.append("'").append( new String(arrays) ).append("'");
						}else if( componetType.isAssignableFrom(char.class)){
							char[] arrays = (char[])propertyValue;
							script.append(" new Array(");
							for(int j=0;j<arrays.length;j++ ){
								script.append("'").append( arrays[j]).append("'");
								if( j!=arrays.length-1 ) script.append(",");
							}
							script.append(")");
						}else if( componetType.isAssignableFrom(short.class)){
							short[] arrays = (short[])propertyValue;
							script.append(" new Array").append( tripBracket(Arrays.toString(arrays)) );
						}else if( componetType.isAssignableFrom(int.class)){
							int[] arrays = (int[])propertyValue;
							script.append(" new Array").append( tripBracket(Arrays.toString(arrays)) );
						}else if( componetType.isAssignableFrom(long.class)){
							long[] arrays = (long[])propertyValue;
							script.append(" new Array").append( tripBracket(Arrays.toString(arrays)) );
						}else if( componetType.isAssignableFrom(float.class)){
							float[] arrays = (float[])propertyValue;
							script.append(" new Array").append( tripBracket(Arrays.toString(arrays)) );
						}else if( componetType.isAssignableFrom(double.class)){
							double[] arrays = (double[])propertyValue;
							script.append(" new Array").append( tripBracket(Arrays.toString(arrays)) );
						}else{
							throw new java.lang.IllegalAccessException("未知数据类型，无法解析");
						}
					}
				}else if( ClassUtils.isPrimitiveWrapper(fieldClass) ){
					//原始数据类型的封装，如int-->Integer,long-->Long等
					if( propertyValue==null ){
						script.append("''");
					}else{
						if( propertyValue.getClass().isAssignableFrom(String.class) ||
								propertyValue.getClass().isAssignableFrom(Character.class)){
							script.append("'").append(propertyValue).append("'");
						}else{
							script.append(propertyValue);
						}							
					}
				}else if( ClassUtils.isPrimitiveWrapperArray(fieldClass) ){
					//原始数据类型数组封装,如 Integer-->new Integer[](),Long-->new Long[]()等
					if( propertyValue==null ){
						script.append("new Array()");
					}else{
						Object[] arrays =(Object[])propertyValue;
						script.append(" new Array(");
						for(int j=0;j<arrays.length;j++ ){
							script.append(arrays[j]);
							if( j!=arrays.length-1 ) script.append(",");
						}
						script.append(")");
					}
				}else if( fieldClass.isAssignableFrom(java.util.Date.class) ){
					//判断是否为日期格式数据类型,普通日期格式内容
					if( propertyValue==null ){
						script.append("''");
					}else{
						script.append("'").append(DateUtil.getDate((java.util.Date)propertyValue)).append("'");
					}
				}else if( fieldClass.isAssignableFrom(java.sql.Date.class) ){
					//判断是否为sql日期格式类型，将内容转换为java.sql.Date格式内容
					if( propertyValue==null ){
						script.append("''");
					}else{
						script.append("'").append(DateUtil.getDate((java.util.Date)propertyValue)).append("'");
					}
				}else if( fieldClass.isAssignableFrom(java.util.Set.class) ||
						 fieldClass.isAssignableFrom(java.util.List.class) || 
						 fieldClass.isAssignableFrom(java.util.Map.class) ){
					//集合对象，由于考虑到内存和效率问题，此出不在循环处理集合类数据集,
					//默认加载20个数据对象
					script.append(" new Array(20)");
				}else{
					//普通的用户自定义类型的数据对象
					script.append( ReflectUtil.toJavascript(propertyValue) );
				}
				if( i!=fields.length-1 ) script.append(",");
			}
		}
		script.append("}");
		return script.toString();
	}
	
	/**
	 * 检查是否为对象标识
	 * @param propertyName 属性名
	 * @return true-是 false-否
	 */
	public static boolean isMobjectIdentify(String propertyName){
		if( propertyName==null || "".equals(propertyName) ) return false;
		return propertyName.substring(propertyName.length()-2).toLowerCase().equals("id");
	}
	
	private static String tripBracket(String value){
		if( value==null ) return "";
		return value.replace('[', '(').replace(']',')');
				
	}
}